namespace OpenComposite.DesignerControls
{
	using System;
	using System.Collections;
	using System.ComponentModel;
	using System.Data;
	using System.Drawing;
	using System.Windows.Forms;

	using OpenComposite.Base;
	using OpenComposite.Base.Collections;
	using OpenComposite.EII;
	using OpenComposite.EII.Repository;
	using OpenComposite.Repository.Properties;
	using OpenComposite.Tools.Base;

	/// <summary>
	/// Summary description for CtrlSelectParticipant.
	/// </summary>
	[ToolboxItem(false)]
	public class CtrlSelectParticipant : System.Windows.Forms.UserControl
	{
		#region Initialization

		/// <summary>
		/// Initializes a new instance of the <see cref="CtrlSelectParticipant"/> class.
		/// </summary>
		public CtrlSelectParticipant()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();

			treeOrgs.ImageList = this.Images;
			lstRoles.SmallImageList = this.Images;
			lstUsers.SmallImageList = this.Images;
		}

		#endregion Initialization

		#region Public Members

		#region Properties

		/// <summary>
		/// Gets and sets images for participants.
		/// </summary>
		public ImageList Images
		{
			get
			{
				if ( m_Images == null ) {
					m_Images = new ImageList();
					m_Images.TransparentColor = Color.Magenta;
					m_Images.ColorDepth = ColorDepth.Depth32Bit;
					m_Images.Images.Add(Resources.png_org);
					m_Images.Images.Add(Resources.png_org);
					m_Images.Images.Add(Resources.png_users);
					m_Images.Images.Add(Resources.png_user);
					m_Images.Images.Add(Resources.delete);
					m_Images.Images.Add(Resources.bmp_mail);
					m_Images.Images.Add(Resources.property);
					m_Images.Images.Add(Resources.png_participantrule);
				}
				return m_Images;
			}
		}

		/// <summary>
		/// Gets the list of selected participant items.
		/// </summary>
		/// <value></value>
		public object[] SelectedItems
		{
			get
			{
				ArrayList parts = new ArrayList();

				if ( m_HasFocus == HasFocus.Orgs ) {
					TreeNode node = treeOrgs.SelectedNode;
					if ( node != null && node.Tag != null ) {
						parts.Add(node.Tag);
					}
				} else if ( m_HasFocus == HasFocus.Users ) {
					foreach ( ListViewItem item in lstUsers.SelectedItems ) {
						if ( item.Tag != null )
							parts.Add(item.Tag);
					}
				} else if ( m_HasFocus == HasFocus.Roles ) {
					foreach ( ListViewItem item in lstRoles.SelectedItems ) {
						if ( item.Tag != null )
							parts.Add(item.Tag);
					}
				}

				return parts.ToArray();
			}
		}

		#endregion Properties

		#region Methods

		/// <summary>
		/// Initialize the control.
		/// </summary>
		public void Init()
		{
			refreshTreeData();
		}

		/// <summary>
		/// Reset control lists.
		/// </summary>
		public void Reset()
		{
			putUsersInList();
			treeOrgs.CollapseAll();
		}

		#endregion Methods

		#endregion Public Members

		#region Protected Members

		#region Methods

		/// <summary> 
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if ( disposing ) {
				if ( components != null ) {
					components.Dispose();
				}
			}
			base.Dispose(disposing);
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			if ( !this.DesignMode ) {
				_organization = Global.Repository.GetItem<Organization>(Global.CurrentUser.OrganizationID);
			}
		}

		#endregion Methods

		#endregion Protected Members

		#region Private Members

		#region Fields

		/// <summary>
		/// Dataset with orgs, roles and users.
		/// </summary>
		private Organization _organization;
		private ToolStripMenuItem cmiTreeRefresh;
		private System.ComponentModel.IContainer components;
		private System.Windows.Forms.GroupBox groupBox1;
		private System.Windows.Forms.GroupBox groupBox2;
		private System.Windows.Forms.GroupBox groupBox3;
		private System.Windows.Forms.ListView lstRoles;
		private System.Windows.Forms.ListView lstUsers;

		/// <summary>
		/// DataAccees over Webservice.
		/// </summary>
		//private string m_OrgId;
		//private string m_OrgName;
		/// <summary>
		/// Control with focus (tree or list).
		/// </summary>
		private HasFocus m_HasFocus;
		private System.Windows.Forms.ImageList m_Images;

		/// <summary>
		/// The selected tree node.
		/// </summary>
		private TreeNode m_SelectedNode = null;
		private SplitContainer splitContainer1;
		private SplitContainer splitContainer2;
		private ContextMenuStrip treeContextMenu;
		private System.Windows.Forms.TreeView treeOrgs;

		#endregion Fields

		#region Event Handlers

		private void cmiTreeRefresh_Click(object sender, EventArgs e)
		{
			try {
				//m_OrgDs = m_data.DataAccess.GetOrgRoleUsers(m_OrgId);
				_organization.Reload();
				refreshTreeData();
			} catch { }
		}

		/// <summary>
		/// Dragover
		/// </summary>
		private void lstRoles_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
		{
			e.Effect = DragDropEffects.Move;
		}

		/// <summary>
		/// Drag item from roles.
		/// </summary>
		private void lstRoles_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
		{
			try {
				if ( e.Button == MouseButtons.Left && lstRoles.SelectedItems.Count > 0 ) {
					DragContainer con = new DragContainer("PTROLE");
					foreach ( ListViewItem itm in lstRoles.SelectedItems ) {
						con.Items.Add(itm.Tag);
					}
					lstRoles.DoDragDrop(con, DragDropEffects.Move);
				}
			} catch { }
		}

		/// <summary>
		/// SelectedIndexChanged on roles list.
		/// </summary>
		private void lstRoles_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			try {
				m_SelectedNode = treeOrgs.SelectedNode;
				treeOrgs.SelectedNode = null;
				m_HasFocus = HasFocus.Roles;
				putRoleUsersInList();
			} catch { }
		}

		/// <summary>
		/// Dragover
		/// </summary>
		private void lstUsers_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
		{
			e.Effect = DragDropEffects.Move;
		}

		/// <summary>
		/// Drag item from users.
		/// </summary>
		private void lstUsers_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
		{
			try {
				if ( e.Button == MouseButtons.Left && lstUsers.SelectedItems.Count > 0 ) {
					DragContainer con = new DragContainer("PTUSER");
					foreach ( ListViewItem itm in lstUsers.SelectedItems ) {
						con.Items.Add(itm.Tag);
					}
					lstUsers.DoDragDrop(con, DragDropEffects.Move);
				}
			} catch { }
		}

		/// <summary>
		/// Selected index of list view.
		/// </summary>
		private void lstUsers_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			m_HasFocus = HasFocus.Users;
		}

		/// <summary>
		/// Click on tree node.
		/// </summary>
		private void treeOrgs_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
		{
			try {
				TreeNode node = e.Node;
				if ( node == null || ( m_SelectedNode == node && m_HasFocus == HasFocus.Orgs ) )
					return;

				lstRoles.SelectedItems.Clear();
				m_HasFocus = HasFocus.None;

				if ( node != null && node.Tag != null ) {
					m_HasFocus = HasFocus.Orgs;
					// Add only users of org unit.
					putUnitUsersInList(node);
				}
			} catch { }
		}

		/// <summary>
		/// Dragover
		/// </summary>
		private void treeOrgs_DragOver(object sender, System.Windows.Forms.DragEventArgs e)
		{
			e.Effect = DragDropEffects.Move;
		}

		private void treeOrgs_Enter(object sender, System.EventArgs e)
		{
			treeOrgs.SelectedNode = m_SelectedNode;
		}

		/// <summary>
		/// Drag item from tree.
		/// </summary>
		private void treeOrgs_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
		{
			try {
				TreeNode node = e.Item as TreeNode;
				if ( e.Button == MouseButtons.Left && node != null && node.Tag != null ) {
					treeOrgs.SelectedNode = node;
					DragContainer con = new DragContainer("PTORG");
					con.Items.Add(node.Tag);
					treeOrgs.DoDragDrop(con, DragDropEffects.Move);
				}
			} catch { }
		}

		#endregion Event Handlers

		#region Methods

		/// <summary> 
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			this.treeOrgs = new System.Windows.Forms.TreeView();
			this.treeContextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
			this.cmiTreeRefresh = new System.Windows.Forms.ToolStripMenuItem();
			this.groupBox1 = new System.Windows.Forms.GroupBox();
			this.groupBox2 = new System.Windows.Forms.GroupBox();
			this.lstRoles = new System.Windows.Forms.ListView();
			this.groupBox3 = new System.Windows.Forms.GroupBox();
			this.lstUsers = new System.Windows.Forms.ListView();
			this.splitContainer1 = new System.Windows.Forms.SplitContainer();
			this.splitContainer2 = new System.Windows.Forms.SplitContainer();
			this.treeContextMenu.SuspendLayout();
			this.groupBox1.SuspendLayout();
			this.groupBox2.SuspendLayout();
			this.groupBox3.SuspendLayout();
			this.splitContainer1.Panel1.SuspendLayout();
			this.splitContainer1.Panel2.SuspendLayout();
			this.splitContainer1.SuspendLayout();
			this.splitContainer2.Panel1.SuspendLayout();
			this.splitContainer2.Panel2.SuspendLayout();
			this.splitContainer2.SuspendLayout();
			this.SuspendLayout();
			//
			// treeOrgs
			//
			this.treeOrgs.AllowDrop = true;
			this.treeOrgs.ContextMenuStrip = this.treeContextMenu;
			this.treeOrgs.Dock = System.Windows.Forms.DockStyle.Fill;
			this.treeOrgs.Location = new System.Drawing.Point(3, 16);
			this.treeOrgs.Name = "treeOrgs";
			this.treeOrgs.Size = new System.Drawing.Size(242, 277);
			this.treeOrgs.TabIndex = 0;
			this.treeOrgs.Enter += new System.EventHandler(this.treeOrgs_Enter);
			this.treeOrgs.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeOrgs_AfterSelect);
			this.treeOrgs.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.treeOrgs_ItemDrag);
			this.treeOrgs.DragOver += new System.Windows.Forms.DragEventHandler(this.treeOrgs_DragOver);
			//
			// treeContextMenu
			//
			this.treeContextMenu.AllowDrop = true;
			this.treeContextMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
			this.cmiTreeRefresh});
			this.treeContextMenu.Name = "treeContextMenu";
			this.treeContextMenu.Size = new System.Drawing.Size(114, 26);
			//
			// cmiTreeRefresh
			//
			this.cmiTreeRefresh.Image = global::OpenComposite.Repository.Properties.Resources.refresh;
			this.cmiTreeRefresh.Name = "cmiTreeRefresh";
			this.cmiTreeRefresh.Size = new System.Drawing.Size(113, 22);
			this.cmiTreeRefresh.Text = "Refresh";
			this.cmiTreeRefresh.Click += new System.EventHandler(this.cmiTreeRefresh_Click);
			//
			// groupBox1
			//
			this.groupBox1.Controls.Add(this.treeOrgs);
			this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.groupBox1.Location = new System.Drawing.Point(0, 0);
			this.groupBox1.Name = "groupBox1";
			this.groupBox1.Size = new System.Drawing.Size(248, 296);
			this.groupBox1.TabIndex = 5;
			this.groupBox1.TabStop = false;
			this.groupBox1.Text = "Organizational Units";
			//
			// groupBox2
			//
			this.groupBox2.Controls.Add(this.lstRoles);
			this.groupBox2.Dock = System.Windows.Forms.DockStyle.Fill;
			this.groupBox2.Location = new System.Drawing.Point(0, 0);
			this.groupBox2.Name = "groupBox2";
			this.groupBox2.Size = new System.Drawing.Size(244, 146);
			this.groupBox2.TabIndex = 6;
			this.groupBox2.TabStop = false;
			this.groupBox2.Text = "Roles";
			//
			// lstRoles
			//
			this.lstRoles.AllowDrop = true;
			this.lstRoles.Dock = System.Windows.Forms.DockStyle.Fill;
			this.lstRoles.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
			this.lstRoles.Location = new System.Drawing.Point(3, 16);
			this.lstRoles.Name = "lstRoles";
			this.lstRoles.Size = new System.Drawing.Size(238, 127);
			this.lstRoles.Sorting = System.Windows.Forms.SortOrder.Ascending;
			this.lstRoles.TabIndex = 1;
			this.lstRoles.UseCompatibleStateImageBehavior = false;
			this.lstRoles.View = System.Windows.Forms.View.List;
			this.lstRoles.SelectedIndexChanged += new System.EventHandler(this.lstRoles_SelectedIndexChanged);
			this.lstRoles.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.lstRoles_ItemDrag);
			this.lstRoles.DragOver += new System.Windows.Forms.DragEventHandler(this.lstRoles_DragOver);
			//
			// groupBox3
			//
			this.groupBox3.Controls.Add(this.lstUsers);
			this.groupBox3.Dock = System.Windows.Forms.DockStyle.Fill;
			this.groupBox3.Location = new System.Drawing.Point(0, 0);
			this.groupBox3.Name = "groupBox3";
			this.groupBox3.Size = new System.Drawing.Size(244, 146);
			this.groupBox3.TabIndex = 7;
			this.groupBox3.TabStop = false;
			this.groupBox3.Text = "Employees";
			//
			// lstUsers
			//
			this.lstUsers.AllowDrop = true;
			this.lstUsers.Dock = System.Windows.Forms.DockStyle.Fill;
			this.lstUsers.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
			this.lstUsers.Location = new System.Drawing.Point(3, 16);
			this.lstUsers.Name = "lstUsers";
			this.lstUsers.Size = new System.Drawing.Size(238, 127);
			this.lstUsers.Sorting = System.Windows.Forms.SortOrder.Ascending;
			this.lstUsers.TabIndex = 2;
			this.lstUsers.UseCompatibleStateImageBehavior = false;
			this.lstUsers.View = System.Windows.Forms.View.List;
			this.lstUsers.SelectedIndexChanged += new System.EventHandler(this.lstUsers_SelectedIndexChanged);
			this.lstUsers.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.lstUsers_ItemDrag);
			this.lstUsers.DragOver += new System.Windows.Forms.DragEventHandler(this.lstUsers_DragOver);
			//
			// splitContainer1
			//
			this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.splitContainer1.Location = new System.Drawing.Point(2, 2);
			this.splitContainer1.Name = "splitContainer1";
			//
			// splitContainer1.Panel1
			//
			this.splitContainer1.Panel1.Controls.Add(this.groupBox1);
			//
			// splitContainer1.Panel2
			//
			this.splitContainer1.Panel2.Controls.Add(this.splitContainer2);
			this.splitContainer1.Size = new System.Drawing.Size(496, 296);
			this.splitContainer1.SplitterDistance = 248;
			this.splitContainer1.TabIndex = 3;
			this.splitContainer1.Text = "splitContainer1";
			//
			// splitContainer2
			//
			this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill;
			this.splitContainer2.Location = new System.Drawing.Point(0, 0);
			this.splitContainer2.Name = "splitContainer2";
			this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal;
			//
			// splitContainer2.Panel1
			//
			this.splitContainer2.Panel1.Controls.Add(this.groupBox2);
			//
			// splitContainer2.Panel2
			//
			this.splitContainer2.Panel2.Controls.Add(this.groupBox3);
			this.splitContainer2.Size = new System.Drawing.Size(244, 296);
			this.splitContainer2.SplitterDistance = 146;
			this.splitContainer2.TabIndex = 0;
			this.splitContainer2.Text = "splitContainer2";
			//
			// CtrlSelectParticipant
			//
			this.Controls.Add(this.splitContainer1);
			this.Name = "CtrlSelectParticipant";
			this.Padding = new System.Windows.Forms.Padding(2);
			this.Size = new System.Drawing.Size(500, 300);
			this.treeContextMenu.ResumeLayout(false);
			this.groupBox1.ResumeLayout(false);
			this.groupBox2.ResumeLayout(false);
			this.groupBox3.ResumeLayout(false);
			this.splitContainer1.Panel1.ResumeLayout(false);
			this.splitContainer1.Panel2.ResumeLayout(false);
			this.splitContainer1.ResumeLayout(false);
			this.splitContainer2.Panel1.ResumeLayout(false);
			this.splitContainer2.Panel2.ResumeLayout(false);
			this.splitContainer2.ResumeLayout(false);
			this.ResumeLayout(false);
		}

		/// <summary>
		/// Fill recursive org sub tree.
		/// </summary>
		/// <param name="node">Actual tree node</param>
		/// <param name="parentId">Id of the parent org unit.</param>
		private void fillOrgTree(TreeNode node, int parentId)
		{
			Organization org = node.Tag as Organization;
			OrganizationalUnit orgunit = node.Tag as OrganizationalUnit;
			BindingListEx<OrganizationalUnit> orgunits = null;
			if ( org != null ) {
				orgunits = org.GetOrgUnits();
			} else if ( orgunit != null ) {
				orgunits = orgunit.GetSubOrgUnits();
			}
			if ( orgunits == null ) return; // EXIT

			foreach ( var ou in orgunits ) {
				// create the tree node.
				TreeNode nd = new TreeNode(ou.Display);
				nd.Tag = ou;
				nd.ImageIndex = (int)ParticipantTypeImageIndex.OrganizationUnit;
				node.Nodes.Add(nd);
				// fill the sub tree.
				fillOrgTree(nd, ou.ID);
			}
		}

		/// <summary>
		/// Put users of role in user list.
		/// </summary>
		private void putRoleUsersInList()
		{
			if ( m_HasFocus == HasFocus.Roles && lstRoles.SelectedItems.Count > 0 ) {
				Role role = lstRoles.SelectedItems[0].Tag as Role;
				if ( role == null ) return; // EXIT

				try {
					// Org unit
					lstUsers.BeginUpdate();
					lstUsers.Items.Clear();

					foreach ( User user in role.GetUsers() ) {
						ListViewItem item = new ListViewItem(user.Display);
						item.Tag = user;
						item.ImageIndex = (int)ParticipantTypeImageIndex.User;
						lstUsers.Items.Add(item);
					}
				} catch ( Exception ex ) {
					Helper.ShowException(ex);
				} finally {
					lstUsers.EndUpdate();
				}
			}
		}

		/// <summary>
		/// Put all org roles in list view.
		/// </summary>
		private void putRolesInList()
		{
			try {
				lstRoles.BeginUpdate();
				this.lstRoles.Items.Clear();

				foreach ( Role role in _organization.GetRoles() ) {
					ListViewItem item = new ListViewItem(role.Display);
					item.Tag = role;
					item.ImageIndex = (int)ParticipantTypeImageIndex.Role;
					lstRoles.Items.Add(item);
				}
			} catch ( Exception ex ) {
				Helper.ShowException(ex);
			} finally {
				lstRoles.EndUpdate();
			}
		}

		/// <summary>
		/// Show unit users in list view.
		/// </summary>
		/// <param name="node">The treenode clicked by the user.</param>
		private void putUnitUsersInList(TreeNode node)
		{
			try {
				// Org
				if ( node.Tag is Organization ) {
					putUsersInList();
					return;
				}

				// Org unit
				lstUsers.BeginUpdate();
				lstUsers.Items.Clear();

				putUnitUsersInList1(node);
			} catch ( Exception ex ) {
				Helper.ShowException(ex);
			} finally {
				lstUsers.EndUpdate();
			}
		}

		/// <summary>
		/// Get recursive users from org tree.
		/// </summary>
		/// <param name="node">The actual treenode.</param>
		private void putUnitUsersInList1(TreeNode node)
		{
			OrganizationalUnit ou = node.Tag as OrganizationalUnit;
			if ( ou == null ) return; // EXIT

			foreach ( User user in ou.GetUsers() ) {
				putUserInList(user);
			}
			foreach ( TreeNode nd in node.Nodes ) {
				putUnitUsersInList1(nd);
			}
		}

		/// <summary>
		/// create a listview item for the user datarow.
		/// </summary>
		/// <param name="row"></param>
		private void putUserInList(User user)
		{
			ListViewItem item = new ListViewItem(user.Display);
			item.Tag = user;
			item.ImageIndex = (int)ParticipantTypeImageIndex.User;
			lstUsers.Items.Add(item);
		}

		/// <summary>
		/// Put all org users in list view.
		/// </summary>
		private void putUsersInList()
		{
			try {
				lstUsers.BeginUpdate();
				lstUsers.Items.Clear();

				foreach ( User user in _organization.GetUsers() ) {
					putUserInList(user);
				}
			} catch ( Exception ex ) {
				Helper.ShowException(ex);
			} finally {
				lstUsers.EndUpdate();
			}
		}

		/// <summary>
		/// Refresh data from db.
		/// </summary>
		private void refreshTreeData()
		{
			try {
				treeOrgs.BeginUpdate();

				// Base tree structure
				treeOrgs.Nodes.Clear();

				// The root node.
				Organization org = _organization;
				TreeNode root = new TreeNode(org.Display);
				root.Tag = org;
				root.ImageIndex = (int)ParticipantTypeImageIndex.Organization;
				treeOrgs.Nodes.Add(root);

				// Fill org tree for org units.
				fillOrgTree(root, -1);

				// Roles and users
				putRolesInList();
				putUsersInList();

				if ( treeOrgs.Nodes.Count > 0 ) {
					treeOrgs.SelectedNode = treeOrgs.Nodes[0];
					treeOrgs.SelectedNode.Expand();
				}

			} catch ( Exception ex ) {
				Helper.ShowException(ex);
			} finally {
				treeOrgs.EndUpdate();
			}
		}

		#endregion Methods

		#endregion Private Members

		#region Enumerations

		private enum HasFocus
		{
			None,
			Orgs,
			Roles,
			Users
		}

		#endregion Enumerations
	}

	#region Enumerations

	/// <summary>
	/// Type of ListObject.
	/// </summary>
	public enum ParticipantTypeImageIndex
	{
		/// <summary>
		/// Organization
		/// </summary>
		Organization = 0,
		/// <summary>
		/// Organizational Unit
		/// </summary>
		OrganizationUnit = 1,
		/// <summary>
		/// Role
		/// </summary>
		Role = 2,
		/// <summary>
		/// User
		/// </summary>
		User = 3,
		/// <summary>
		/// Activity
		/// </summary>
		Activity = 4,
		/// <summary>
		/// EmailAddress
		/// </summary>
		Email = 5,
		/// <summary>
		/// Property
		/// </summary>
		Property = 6
	}

	#endregion Enumerations
}